Skip to content

Conversation

@maxisbey
Copy link
Contributor

@maxisbey maxisbey commented Feb 2, 2026

Replace the decorator-based handler registration on the lowlevel Server with direct on_* keyword arguments on the constructor. Handlers are now raw callables with a uniform (ctx, params) -> result signature, dispatched by method string.

Supersedes #1968.

@maxisbey maxisbey changed the base branch from sketch/lowlevel-server-v2 to main February 3, 2026 14:06
@maxisbey maxisbey force-pushed the sketch/lowlevel-server-v2-kwargs branch from acea3d7 to 8e1d947 Compare February 3, 2026 15:27
@maxisbey maxisbey changed the title refactor: replace Handler objects with on_* constructor kwargs refactor: replace lowlevel Server decorators with on_* constructor kwargs Feb 3, 2026
@claude
Copy link

claude bot commented Feb 3, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@maxisbey maxisbey marked this pull request as draft February 3, 2026 15:41
@maxisbey maxisbey force-pushed the sketch/lowlevel-server-v2-kwargs branch 2 times, most recently from 7221cca to 7e9e53f Compare February 9, 2026 13:38
…args

Replace the decorator-based handler registration on the lowlevel Server with
direct on_* keyword arguments on the constructor. Handlers are raw callables
with a uniform (ctx, params) -> result signature.

- Server constructor takes on_list_tools, on_call_tool, etc.
- String-keyed dispatch instead of type-keyed
- Remove RequestT generic from Server (transport-specific, not bound at construction)
- Delete handler.py and func_inspection.py (no longer needed)
- Update ExperimentalHandlers to use callback-based registration
- Update MCPServer to pass on_* kwargs via _create_handler_kwargs()
- Update migration docs and docstrings
- Fix all migration.md examples to use ServerRequestContext instead of RequestContext
- Fix all imports to use 'from mcp.server import Server, ServerRequestContext'
- Apply ruff formatting to code examples
- Add Server constructor calls to examples that were missing them
- Re-export ServerRequestContext from mcp.server.__init__
- Add type hints to TaskResultHandler docstring example
…erver

Move handler functions from a dict-returning method to private methods
on MCPServer, passed directly to the Server constructor by name. This
eliminates the **kwargs unpacking pattern and makes the handler
registration explicit.
Allow users to override default task handlers by passing on_get_task,
on_task_result, on_list_tasks, and on_cancel_task to enable_tasks().
User-provided handlers are registered first; defaults fill in the rest.
The subscribe capability in ResourcesCapability was hardcoded to False,
even when on_subscribe_resource handler was provided. Now dynamically
checks whether a subscribe handler is registered.

Also applies ruff formatting to experimental.py.
@maxisbey maxisbey force-pushed the sketch/lowlevel-server-v2-kwargs branch from e9df629 to ca8fd2e Compare February 11, 2026 15:16
Migrate test files from the old decorator-based handler registration
to the new on_* constructor kwargs pattern. Key changes:

- Replace @server.list_tools(), @server.call_tool(), etc. decorators
  with on_list_tools, on_call_tool, etc. kwargs on Server()
- Replace server.request_context access with ctx parameter
  (first argument to all handlers)
- Handlers now receive (ctx, params) and return full result types
  (e.g. ListToolsResult instead of list[Tool])
- Convert experimental task decorators to enable_tasks() kwargs
- Add LifespanContextT default to ServerRequestContext
- Widen on_call_tool return type to include CreateTaskResult
- Delete redundant tests/shared/test_memory.py
- Simplify tests to use Client where possible
Convert the 3 remaining experimental task server test files:
- test_integration.py: proper lifespan + Client pattern
- test_run_task_flow.py: constructor kwargs + Client pattern
- test_server.py: enable_tasks() kwargs + Client pattern

All tests use proper typing with ServerRequestContext and
constructor kwargs instead of decorators.
- Delete test_func_inspection.py (tested removed create_call_wrapper)
- Delete test_lowlevel_input_validation.py and test_lowlevel_output_validation.py
  (tested jsonschema validation removed from low-level server)
- Migrate test_read_resource.py to E2E with Client
- Migrate test_129_resource_templates.py to E2E with Client
- Migrate test_output_schema_validation.py to constructor kwargs
  (removed bypass_server_output_validation hack, no longer needed)
- Migrate test_ws.py, test_sse.py, test_streamable_http.py from Server
  subclasses with decorators to standalone handlers with constructor kwargs
- Replace self.request_context contextvar with ctx parameter
- Replace global _server_lock with typed ServerState lifespan context
- Fix import paths for TextContent, ClientRegistrationOptions,
  RevocationOptions, StreamableHTTPServerTransport
enable_tasks registers default handlers for all task methods, so
partial capabilities aren't currently possible. Skipped tests with
TODO(maxisbey) to revisit when low-level API supports selectively
enabling/disabling individual task capabilities.
…attern

- Convert all low-level Server examples from decorator-based handlers
  to constructor on_* kwargs pattern
- Replace server.request_context with ctx parameter passed to handlers
- Replace auto-wrapped return values (dict, str, bytes) with explicit
  result type construction (CallToolResult, ReadResourceResult, etc.)
- Update everything-server to use _add_request_handler for subscribe/
  unsubscribe/logging handlers (MCPServer doesn't expose these yet)
- Update migration docs with detailed section on removed auto-wrapping
- Update README snippets
Remove references to automatic content/structured conversion and
the four return type options that no longer exist. Low-level handlers
now always return CallToolResult directly.
- Remove unused _add_notification_handler from Server
- Add pragma no cover for dead dict code path in MCPServer._handle_call_tool
- Add E2E test for MCPServer.completion() decorator
- Replace unused handle_list_tools stubs with raise NotImplementedError
- Add pragma no cover for skipped tests in test_server and test_spec_compliance
- Flatten nested completion handler logic to eliminate untaken branches
- Fix test_88_random_error to use assert + shared return path
- Clean up unused imports (Tool, ToolExecution, TASK_REQUIRED)
@maxisbey maxisbey marked this pull request as ready for review February 11, 2026 22:55
@maxisbey
Copy link
Contributor Author

Although CI is all green, I still want to manually test all the examples that were modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants